
#include <iostream>
using namespace std;

template <class T>
class shared_ptr
{
public:
    shared_ptr(T* ptr)
        :_ptr(ptr),_count(new int(1))
    {}

    shared_ptr() = default;

    ~shared_ptr()//对象销毁时自动调用析构函数
    {
        if(--(*_count) == 0)//析构要确保引用计数为0
        {
            delete[] _ptr;
            delete _count;
            cout << "释放空间" << endl;
        }
    }

    shared_ptr(const shared_ptr<T>& sp)//准备生成的对象才调用拷贝构造
        :_ptr(sp._ptr),_count(sp._count)
    {
        ++(*_count);
    }

    shared_ptr<T>& operator=(const shared_ptr<T>& sp)
    {
        if(this != &sp)//排除自己给自己赋值
        {
            if(--(*_count) == 0)//把以前的引用释放
            {
                delete[] _ptr;
                delete _count;
                cout << "释放空间" << endl;
            }
            _ptr = sp._ptr;
            _count = sp._count;
            ++_count;
        }
        return *this;
    }

    T& operator*()
    {
        return *_ptr;
    }
    
    T* operator->()
    {
        return *_ptr;
    }

    T& operator[](size_t n)
    {
        return _ptr[n];
    }
private:
    T* _ptr;
    int* _count;
};

int main()
{
    shared_ptr<int> sp1(new int(0));
    shared_ptr<int> sp2(sp1);

    cout << *sp1 << " " << *sp2 << endl;
    (*sp1)++;
    (*sp2)++;
    cout << *sp1 << " " << *sp2 << endl;

    shared_ptr<int> sp3(new int(1));
    shared_ptr<int> sp4(new int(3));
    cout << *sp3 << " " << *sp4 << endl;

    sp4 = sp3;

    cout << *sp3 << " " << *sp4 << endl;
    (*sp3)++;
    (*sp4)++;
    cout << *sp3 << " " << *sp4 << endl;
    return 0;
}


// #include <iostream>
// #include <memory>
// using namespace std;

// double div(double x,double y)
// {
//     if(y == 0)
//     {
//         throw string("除0错误");
//     }
//     else 
//     {
//         return x / y;
//     }
// }

// void func()
// {
//     // auto_ptr<int> ap1(new int[10]{0});
//     // auto_ptr<int> ap2(ap1);
//     // (*ap1)++;//拷贝之后，ap1就变成空指针了
//     // (*ap2)++;

//     // unique_ptr<int> up1(new int[10]{0});
//     // unique_ptr<int> up2(up1);//直接不允许拷贝

//     shared_ptr<int> sp1(new int[10]{0});
//     shared_ptr<int> sp2(sp1);
//     (*sp1)++;
//     (*sp2)++;//引用计数解决问题
    
//     double left = 0,right = 0;
//     cin >> left >> right;
//     cout << div(left,right) << endl;
// }

// int main()
// {
//     try
//     {
//         func();
//     }
//     catch(const string& s)
//     {
//         cout << s << endl;
//     }
//     catch(...)
//     {
//         cout << "Unknown Error" << endl;
//     }
//     return 0;
// }


// #include <iostream>
// #include <string>
// using namespace std;
// #include <unistd.h>

// // 模拟一下工程上如何抛异常

// class Exception//基类
// {
// public:
//     Exception(const string& msg,const int& id)
//         :_msg(msg),_id(id)
//     {}

//     virtual string what() const
//     {
//         string str = _msg;
//         str += ":";
//         str += to_string(_id);
//         return str;
//     }

// protected:
//     string _msg;//异常信息
//     int _id;//异常码
// };

// class ServerException : public Exception
// {
// public:
//     ServerException(const string& msg,const int& id)
//         :Exception(msg,id)
//     {}

//     virtual string what() const
//     {
//         string str = "ServerException:";
//         str += _msg;
//         str += ":";
//         str += to_string(_id);
//         return str;
//     }
// private:
// };

// class CacheException : public Exception
// {
// public:
//     CacheException(const string& msg,const int& id)
//         :Exception(msg,id)
//     {}

//     virtual string what() const
//     {
//         string str = "CacheException:";
//         str += _msg;
//         str += ":";
//         str += to_string(_id);
//         return str;
//     }
// private:
// };

// class SqlException : public Exception
// {
// public:
//         SqlException(const string& msg,const int& id)
//         :Exception(msg,id)
//     {}

//     virtual string what() const
//     {
//         string str = "SqlException:";
//         str += _msg;
//         str += ":";
//         str += to_string(_id);
//         return str;
//     }
// private:
// };

// void Sql()
// {
//     srand(time(0));
//     if(rand() % 4 == 0)
//     {
//         throw SqlException("请求错误",100);
//     }
//     else if(rand() % 9 == 0)
//     {
//         throw SqlException("权限错误",200);
//     }
// }

// void Cache()
// {
//     srand(time(0));
//     if(rand() % 2 == 0)
//     {
//         throw CacheException("请求错误",100);
//     }
//     else if(rand() % 4 == 0)
//     {
//         throw CacheException("权限错误",200);
//     }
//     Sql();
// }

// void Server()
// {
//     srand(time(0));
//     if(rand() % 3 == 0)
//     {
//         throw ServerException("请求错误",100);
//     }
//     else if(rand() % 5 == 0)
//     {
//         throw ServerException("权限错误",200);
//     }
//     Cache();
// }

// int main()
// {
//     while(true)
//     {
//         try
//         {
//             Server();
//         }
//         catch(Exception& ep)
//         {
//             cout << ep.what() << endl;
//         }
//         catch(...)
//         {
//             cout << "Unknown Error" << endl;
//         }
//         sleep(1);
//     }
//     return 0;
// }